namespace Microsoft.Robotics.Core.Algorithms
{
    /// <summary>
    /// Generic PID controller interface
    /// </summary>
    public interface IGenericPidController
    {
        /// <summary>
        /// Gets or sets proportional gain parameter. Public set to allow tuning.
        /// </summary>
        double ProportionalGain { get; set; }

        /// <summary>
        /// Gets or sets integral gain parameter. Public set to allow tuning.
        /// </summary>
        double IntegralGain { get; set; }

        /// <summary>
        /// Gets or sets derivative gain parameter. Public set to allow tuning.
        /// </summary>
        double DerivativeGain { get; set; }

        /// <summary>
        /// Evaluates output based on current measurement error and time of measurement. P,I,D parameters are assumed to have been set 
        /// prior to the call.
        /// </summary>
        /// <param name="measuredValue">Measurement Error</param>
        /// <param name="measurementTimeTicks">Measurement time in ticks. At this abstract interface level, tick is a logical
        /// concept. It can be hours, nanoseconds, or just a counter that's incremented with each call (or not). Implementations
        /// of this interface may start making assumptions about the exact measurement units</param>
        /// <returns>Output value</returns>
        double Evaluate(double measuredValue, long measurementTimeTicks);

        /// <summary>
        /// Evaluates output based on current measurement error and time of measurement, and directly supplied P,I,D parameters.
        /// This entry point's implementations shall ignore KP, KI, KP attributes even if they have been set, and use 
        /// supplied parameters. 
        /// </summary>
        /// <param name="measuredError">Measurement Error</param>
        /// <param name="measurementTimeTicksMicroseconds">Measurement time in ticks. At this abstract interface level, tick is a logical
        /// concept. It can be hours, nanoseconds, or just a counter that's incremented with each call (or not). Implementations
        /// of this interface may start making assumptions about the exact measurement units</param>
        /// <param name="proportionalGain">Proportional Parameter that will override KP for this one measurement</param>
        /// <param name="integralGain">Integral Parameter that will override KI for this one measurement</param>
        /// <param name="derivativeGain">Derivative Parameter that will override KD for this one measurement</param>
        /// <returns>Output value</returns>
        double Evaluate(
            double measuredError, 
            long measurementTimeTicksMicroseconds, 
            double proportionalGain, 
            double integralGain, 
            double derivativeGain);
    }
}
